﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Data.SQLite;

namespace PathSearcher
{
    class Tables
    {
        SQLiteConnection connection;
        private Dictionary<int, Dictionary<int, List<Zaznam>>> table;
        private Dictionary<int, Dictionary<int, List<Zaznam>>> tableDestination;

        public Tables()
        {
            this.connection = Database.GetConnection();
            table = new Dictionary<int, Dictionary<int, List<Zaznam>>>();
            tableDestination = new Dictionary<int, Dictionary<int, List<Zaznam>>>();
            FillDictionary();
        }

        public void FillDictionary()
        {
            SQLiteCommand command = new SQLiteCommand(connection);
            command.CommandText = "SELECT * FROM reacheable_table";

            using (command)
            {
                using (SQLiteDataReader reader = command.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        Zaznam zaznam = new Zaznam();
                        zaznam.Destination = int.Parse(reader["destination_station_id"].ToString());
                        zaznam.Distance = int.Parse(reader["distance"].ToString());
                        zaznam.Line = int.Parse(reader["line_id"].ToString());
                        zaznam.Start = int.Parse(reader["start_station_id"].ToString());

                        if (!table.ContainsKey(zaznam.Start))
                        {
                            table.Add(zaznam.Start, new Dictionary<int, List<Zaznam>>());
                        }
                        if (!table[zaznam.Start].ContainsKey(zaznam.Destination))
                        {
                            table[zaznam.Start].Add(zaznam.Destination, new List<Zaznam>());
                        }
                        table[zaznam.Start][zaznam.Destination].Add(zaznam);

                        // opposite direction 
                        if (!tableDestination.ContainsKey(zaznam.Destination))
                        {
                            tableDestination.Add(zaznam.Destination, new Dictionary<int, List<Zaznam>>());
                        }
                        if (!tableDestination[zaznam.Destination].ContainsKey(zaznam.Start))
                        {
                            tableDestination[zaznam.Destination].Add(zaznam.Start, new List<Zaznam>());
                        }
                        tableDestination[zaznam.Destination][zaznam.Start].Add(zaznam);
                    }

                }
            }
        }

        public IEnumerable<Zaznam> GetReachableStations(int id)
        {
            List<Zaznam> result = new List<Zaznam>();
            foreach (List<Zaznam> item in table[id].Values)
            {
                foreach (Zaznam item2 in item)
                {
                    result.Add(item2);
                }
            }

            return result;
        }


        public IEnumerable<Zaznam> GetSourceStations(int id)
        {
            List<Zaznam> result = new List<Zaznam>();
            foreach (List<Zaznam> item in tableDestination[id].Values)
            {
                foreach (Zaznam item2 in item)
                {
                    result.Add(item2);
                }
            }

            return result;
        }

        public IEnumerable<List<Zaznam>> GetReachableStations(int id, List<Line> excludedLine)
        {
            List<List<Zaznam>> result = new List<List<Zaznam>>();
            foreach (List<Zaznam> item in table[id].Values)
            {
                List<Zaznam> z = new List<Zaznam>();
                foreach (Zaznam item2 in item)
                {
                    if (excludedLine.Find(x => x.LineID == item2.Line) == null)
                    {
                        z.Add(item2);
                    }
                }
                if (z.Count != 0) {
                    result.Add(z);
                }
            }

            return result;
        }

        public IEnumerable<List<Zaznam>> GetSourceStations(int id, List<Line> excludedLine)
        {
            List<List<Zaznam>> result = new List<List<Zaznam>>();
            foreach (List<Zaznam> item in tableDestination[id].Values)
            {
                List<Zaznam> z = new List<Zaznam>();
                foreach (Zaznam item2 in item)
                {
                    if (excludedLine.Find(x => x.LineID==item2.Line)==null )
                    {
                        z.Add(item2);
                    }
                }
                if (z.Count != 0)
                {
                    result.Add(z);
                }
            }

            return result;
        }
    }

    class Zaznam
    {
        public int Start { get; set; }
        public int Destination { get; set; }
        public int Line { get; set; }
        public int Distance { get; set; }
    }


}
